'use client';

import React, { useEffect, useState, useRef } from 'react';
import * as Cesium from 'cesium';

// 北斗网格分级标准（根据GB/T 39409-2020标准）
const GRID_LEVELS = {
  // 一级网格：按GB/T 13989-2012中1:100万地形图图幅划分，网格大小为6°×4°
  1: { 
    latStep: 4, 
    lonStep: 6, 
    color: Cesium.Color.ORANGE.withAlpha(0),
    name: '一级网格',
    description: '6°×4°'
  },
  // 二级网格：将1级网格等分12×8份，形成30′×30′网格
  2: { 
    latStep: 30/60, 
    lonStep: 30/60, 
    color: Cesium.Color.ORANGE.withAlpha(0),
    name: '二级网格',
    description: '30′×30′'
  },
  // 三级网格：将2级网格等分2×3份，形成15′×10′网格，对应1:5万地形图图幅
  3: { 
    latStep: 10/60, 
    lonStep: 15/60, 
    color: Cesium.Color.ORANGE.withAlpha(0),
    name: '三级网格',
    description: '15′×10′'
  },
  // 四级网格：将3级网格等分15×10份，形成1′×1′网格
  4: { 
    latStep: 1/60, 
    lonStep: 1/60, 
    color: Cesium.Color.ORANGE.withAlpha(0),
    name: '四级网格',
    description: '1′×1′'
  },
  // 五级网格：将4级网格等分15×15份，形成4″×4″网格
  5: { 
    latStep: 4/3600, 
    lonStep: 4/3600, 
    color: Cesium.Color.ORANGE.withAlpha(0),
    name: '五级网格',
    description: '4″×4″'
  }
};

// 江门市蓬江区边界范围
const PENGJIANG_BOUNDS = {
  west: 112.95,  // 左边界经度
  east: 113.15,  // 右边界经度
  south: 22.55,  // 下边界纬度
  north: 22.65   // 上边界纬度
};

// 网格字符映射
const GRID_CHAR_MAPPING = {
  // 第一级网格纬度编码（A-V对应0°-4°, 4°-8°, ..., 84°-88°）
  LAT_LEVEL_1: 'ABCDEFGHIJKLMNOPQRSTUV',
  // 第二级网格经度编码（0-B对应12进制）
  LON_LEVEL_2: '0123456789AB',
  // 第二级网格纬度编码（0-7对应8进制）
  LAT_LEVEL_2: '01234567',
  // 第三级网格Z序编码（0-5对应6个区域）
  LEVEL_3_Z_ORDER: '012345',
  // 第四级网格经度编码（0-E对应15进制）
  LON_LEVEL_4: '0123456789ABCDE',
  // 第四级网格纬度编码（0-9对应10进制）
  LAT_LEVEL_4: '0123456789',
  // 第五级网格经纬度编码（0-E对应15进制）
  LEVEL_5: '0123456789ABCDE'
};

interface BeidouGridLayerProps {
  viewer: Cesium.Viewer | null;
  gridLevel?: number; // 默认网格级别
  maxHeight?: number; // 网格最大高度
  showGridCodes?: boolean; // 是否显示网格编码
  enableDynamicLevel?: boolean; // 是否启用动态级别
}

const BeidouGridLayer: React.FC<BeidouGridLayerProps> = ({
  viewer,
  gridLevel = 2,
  maxHeight = 5000,
  showGridCodes = true,
  enableDynamicLevel = true
}) => {
  const [currentLevel, setCurrentLevel] = useState<number>(gridLevel);
  const entitiesRef = useRef<Cesium.Entity[]>([]);
  
  // 清除已有网格
  const clearGrids = () => {
    if (viewer && entitiesRef.current.length > 0) {
      entitiesRef.current.forEach(entity => {
        if (entity && viewer.entities.contains(entity)) {
          viewer.entities.remove(entity);
        }
      });
      entitiesRef.current = [];
    }
  };
  
  // 根据相机高度确定网格级别
  const determineGridLevel = (height: number): number => {
    if (height > 10000000) return 1;  // 非常高，显示一级网格
    if (height > 1000000) return 2;   // 很高，显示二级网格
    if (height > 100000) return 3;    // 高，显示三级网格
    if (height > 10000) return 4;     // 中等高度，显示四级网格
    return 5;                        // 很低，显示五级网格
  };
  
  // 生成标准北斗二维网格编码
  const generateBeidouGridCode = (lon: number, lat: number, level: number): string => {
    // 检查是否是南北极区域 (±88°~90°)
    if (Math.abs(lat) >= 88 && Math.abs(lat) <= 90) {
      return generatePolarGridCode(lon, lat, level);
    }
    
    // 非极地区域标准编码
    const isNorth = lat >= 0;
    const latPrefix = isNorth ? 'N' : 'S';
    
    // 处理负经度（西经）
    let absLon = lon;
    while (absLon < 0) {
      absLon += 360; // 将西经转换为0-360范围
    }
    absLon = absLon % 360; // 标准化到0-360范围
    
    const absLat = Math.abs(lat);
    
    // 第1级网格：半球标识 + 经度 + 纬度
    // 经度：1-60（每6°一个单位）
    const lonLevel1 = Math.floor(absLon / 6) + 1; // 1-60范围
    const lonLevel1Str = lonLevel1.toString().padStart(2, '0');
    
    // 纬度：A-V（每4°一个单位，从赤道开始）
    const latLevel1Index = Math.floor(absLat / 4);
    const latLevel1Char = GRID_CHAR_MAPPING.LAT_LEVEL_1[latLevel1Index];
    
    // 构建一级网格码
    let gridCode = `${latPrefix}${lonLevel1Str}${latLevel1Char}`;
    
    // 如果只需要一级网格码，则返回
    if (level === 1) return gridCode;
    
    // 计算经纬度在该一级网格内的余数
    const lonRemainder = absLon % 6;
    const latRemainder = absLat % 4;
    
    // 第2级网格：12进制经度 + 8进制纬度
    // 经度：0-B（每30′一个单位）
    const lonLevel2 = Math.floor(lonRemainder / 0.5); // 0-11范围
    const lonLevel2Char = GRID_CHAR_MAPPING.LON_LEVEL_2[lonLevel2];
    
    // 纬度：0-7（每30′一个单位）
    const latLevel2 = Math.floor(latRemainder / 0.5); // 0-7范围
    const latLevel2Char = GRID_CHAR_MAPPING.LAT_LEVEL_2[latLevel2];
    
    // 添加二级网格码
    gridCode += `${lonLevel2Char}${latLevel2Char}`;
    
    // 如果只需要二级网格码，则返回
    if (level === 2) return gridCode;
    
    // 计算经纬度在该二级网格内的余数
    const lonRemainder2 = lonRemainder % 0.5;
    const latRemainder2 = latRemainder % 0.5;
    
    // 第3级网格：Z序曲线编码（0-5）
    // 将30′×30′网格划分为2×3份（经度15′、纬度10′）
    const lonLevel3 = Math.floor(lonRemainder2 / 0.25); // 0-1范围
    const latLevel3 = Math.floor(latRemainder2 / (1/6)); // 0-2范围
    
    // 计算Z序曲线索引
    const zOrderIndex = latLevel3 * 2 + lonLevel3; // 0-5范围
    const level3Char = GRID_CHAR_MAPPING.LEVEL_3_Z_ORDER[zOrderIndex];
    
    // 添加三级网格码
    gridCode += level3Char;
    
    // 如果只需要三级网格码，则返回
    if (level === 3) return gridCode;
    
    // 计算经纬度在该三级网格内的余数
    // 确定三级网格的经纬度范围
    const lonLevel3Base = Math.floor(absLon / 6) * 6 + Math.floor(lonRemainder / 0.5) * 0.5 + Math.floor(lonRemainder2 / 0.25) * 0.25;
    const latLevel3Base = Math.floor(absLat / 4) * 4 + Math.floor(latRemainder / 0.5) * 0.5 + Math.floor(latRemainder2 / (1/6)) * (1/6);
    
    // 计算经纬度在该三级网格内的位置
    const lonWithinLevel3 = absLon - lonLevel3Base;
    const latWithinLevel3 = absLat - latLevel3Base;
    
    // 第4级网格：15进制经度 + 10进制纬度（1′×1′）
    // 经度：0-E（每1′一个单位）
    const lonLevel4 = Math.floor(lonWithinLevel3 / (1/60)); // 0-14范围
    const lonLevel4Char = GRID_CHAR_MAPPING.LON_LEVEL_4[lonLevel4];
    
    // 纬度：0-9（每1′一个单位）
    const latLevel4 = Math.floor(latWithinLevel3 / (1/60)); // 0-9范围
    const latLevel4Char = GRID_CHAR_MAPPING.LAT_LEVEL_4[latLevel4];
    
    // 添加四级网格码
    gridCode += `${lonLevel4Char}${latLevel4Char}`;
    
    // 如果只需要四级网格码，则返回
    if (level === 4) return gridCode;
    
    // 计算经纬度在该四级网格内的余数
    const lonLevel4Base = lonLevel3Base + lonLevel4 * (1/60);
    const latLevel4Base = latLevel3Base + latLevel4 * (1/60);
    
    const lonWithinLevel4 = absLon - lonLevel4Base;
    const latWithinLevel4 = absLat - latLevel4Base;
    
    // 第5级网格：15进制经度 + 15进制纬度（4″×4″）
    // 经度：0-E（每4″一个单位）
    const lonLevel5 = Math.floor(lonWithinLevel4 / (4/3600)); // 0-14范围
    const lonLevel5Char = GRID_CHAR_MAPPING.LEVEL_5[lonLevel5];
    
    // 纬度：0-E（每4″一个单位）
    const latLevel5 = Math.floor(latWithinLevel4 / (4/3600)); // 0-14范围
    const latLevel5Char = GRID_CHAR_MAPPING.LEVEL_5[latLevel5];
    
    // 添加五级网格码
    gridCode += `${lonLevel5Char}${latLevel5Char}`;
    
    return gridCode;
  };
  
  // 生成南北极区域的网格编码（简化实现）
  const generatePolarGridCode = (lon: number, lat: number, level: number): string => {
    const isPolarNorth = lat >= 88;
    const prefix = isPolarNorth ? 'N' : 'S';
    
    // 第一级极地网格编码固定为"N000"或"S000"
    let gridCode = `${prefix}000`;
    
    if (level === 1) return gridCode;
    
    // 第二级极地网格：将2°×2°按经度划分为16个30′×30′网格
    // 此处仅为简化实现，实际应按标准详细计算
    const normLon = ((lon % 360) + 360) % 360; // 标准化到0-360范围
    const sector = Math.floor(normLon / 22.5); // 0-15范围，将360°划分为16份
    const row = Math.floor(Math.abs(lat - (isPolarNorth ? 88 : -88)) / 0.5); // 0-3范围
    
    const level2Index = row * 4 + (sector % 4);
    gridCode += level2Index.toString().padStart(2, '0');
    
    return gridCode;
  };
  
  // 绘制网格
  const drawGrids = (level: number) => {
    if (!viewer) return;
    
    clearGrids();
    
    const gridConfig = GRID_LEVELS[level as keyof typeof GRID_LEVELS];
    if (!gridConfig) return;
    
    const { latStep, lonStep, color } = gridConfig;
    
    // 使用固定的江门市蓬江区边界范围，不再使用相机视图范围
    const west = PENGJIANG_BOUNDS.west;
    const east = PENGJIANG_BOUNDS.east;
    const south = PENGJIANG_BOUNDS.south;
    const north = PENGJIANG_BOUNDS.north;
    
    // 根据网格标准计算起始点和结束点，确保网格对齐标准分割
    // 对于一级网格是6°×4°对齐，二级网格是30′×30′对齐，以此类推
    const startLon = Math.floor(west / lonStep) * lonStep;
    const endLon = Math.ceil(east / lonStep) * lonStep;
    const startLat = Math.floor(south / latStep) * latStep;
    const endLat = Math.ceil(north / latStep) * latStep;
    
    // 计算网格数量，限制最大数量避免性能问题
    const maxGrids = level <= 3 ? 30000 : 25000; // 限制总网格数量，低级别网格可以显示更多
    const maxPerDimension = Math.sqrt(maxGrids); // 每个维度的最大网格数
    
    // 根据区域大小和网格层级调整网格密度
    const lonCount = Math.min(Math.ceil((endLon - startLon) / lonStep), maxPerDimension);
    const latCount = Math.min(Math.ceil((endLat - startLat) / latStep), maxPerDimension);
    
    // 优化网格生成，避免微小偏差导致的重叠
    // 使用精确的网格边界计算而不是均分方式
    for (let i = 0; i < lonCount; i++) {
      const west = startLon + i * lonStep;
      const east = west + lonStep;
      
      for (let j = 0; j < latCount; j++) {
        const south = startLat + j * latStep;
        const north = south + latStep;
        
        // 创建网格立方体，使用精确的经纬度边界
        const entity = viewer.entities.add({
          name: `Grid-${i}-${j}`,
          rectangle: {
            coordinates: Cesium.Rectangle.fromDegrees(west, south, east, north),
            height: 0,
            extrudedHeight: maxHeight / 10, // 降低高度，减少视觉重叠
            material: color,
            outline: true,
            outlineColor: Cesium.Color.ORANGE,
            outlineWidth: 1,
            shadows: Cesium.ShadowMode.DISABLED
          }
        });
        
        entitiesRef.current.push(entity);
        
        // 添加网格编码标签
        if (showGridCodes) {
          const gridCode = generateBeidouGridCode(west, south, level);
          const labelEntity = viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(
              (west + east) / 2,
              (south + north) / 2,
              maxHeight / 10 + 50 // 略高于网格顶部
            ),
            label: {
              text: gridCode,
              font: '12px sans-serif',
              fillColor: Cesium.Color.WHITE,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              outlineWidth: 2,
              outlineColor: Cesium.Color.BLACK,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              pixelOffset: new Cesium.Cartesian2(0, -10),
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scale: 0.8 // 略微缩小标签，减少重叠
            }
          });
          
          entitiesRef.current.push(labelEntity);
        }
      }
    }
  };
  
  // 监听相机高度变化，动态调整网格级别
  useEffect(() => {
    if (!viewer || !enableDynamicLevel) return;
    
    const cameraChangedCallback = () => {
      const cameraHeight = viewer.camera.positionCartographic.height;
      const newLevel = determineGridLevel(cameraHeight);
      
      if (newLevel !== currentLevel) {
        setCurrentLevel(newLevel);
        drawGrids(newLevel);
      }
    };
    
    // 添加相机变化事件监听
    viewer.camera.changed.addEventListener(cameraChangedCallback);
    
    // 初始绘制
    drawGrids(currentLevel);
    
    return () => {
      if (viewer && !viewer.isDestroyed()) {
        viewer.camera.changed.removeEventListener(cameraChangedCallback);
        clearGrids();
      }
    };
  }, [viewer, enableDynamicLevel, currentLevel]);
  
  // 初始化时绘制一次网格，不随相机变化而重绘
  useEffect(() => {
    if (viewer) {
      drawGrids(gridLevel);
    }
    
    return () => {
      clearGrids();
    };
  }, [viewer, gridLevel]);
  
  return null; // 这是一个功能组件，不需要渲染UI
};

export default BeidouGridLayer;

// 添加Cesium全局变量的类型声明，确保与CesiumMap.tsx中的声明兼容
declare global {
  interface Window {
    Cesium: typeof Cesium;
  }
} 